//@author wtfumlomglol
package amm.Graphic;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

//objektumok letrehozasaert, utemezes biztositasaert
//es az elpusztitasaert felelos osztaly
public class Game {
    //a jatek fut

    private boolean running = true;
    //varos referenciaja
    private City city = new City();
    //utemezo referenciaja
    private Ticker ticker;
    //pontszam. nem resze a skeletonnak
    private int score = 0;
    //naplozo referenciaja
    private Logger logger = new Logger();
    //grafikus felület értesítéséhez referencia
    private DisplayController displayControl;
    //a játékban eltelt krörök számát jelzi
    private int turns;
    //idő kiírásához
    private int time=0;

    public Game(DisplayController dc)
    {
        this.displayControl = dc;
        
    }

    //atadja a naplozo objektum referenciajat
    public Logger getLogger() {
        return logger;
    }

    //adott időnek a string formátumú megadása
    public String gettime()
    {
        time = ticker.gettime();
        if(time<10) return "0:0"+Integer.toString(time);
        if(time<60 && time>=10) return "0:"+Integer.toString(time);
        else {
            int n=time/60;
            if(time%60<10) return Integer.toString(n)+":0"+Integer.toString(time%60);
            else return Integer.toString(n)+":"+Integer.toString(time%60);
        }
    }
    //letrehoz egy uj bankrablot
    public Criminal createCriminal() {
        Criminal cr = new Criminal(this);
        city.addCriminal(cr);
        return cr;
    }

    //letrehoz egy uj civilt
    public Citizen createCitizen() {
        Citizen cz = new Citizen(this, city.getCitizenLength());
        city.addCitizen(cz);
        return cz;
    }

    //letrehoz egy uj rendort
    public Police createPolice() {
        Police p = new Police(this, city.getPoliceLength());
        city.addPolice(p);
        return p;
    }

    //letrehoz egy uj utat
    public Road createRoad() {
        Road r = new Road(city.getRoadLength());
        city.addRoad(r);
        return r;
    }

    //letrehoz egy uj keresztezodest
    public XRoads createXRoads(Compass c) {
        XRoads xr;
        if (c == null) {
            xr = new XRoads(city.getXRoadsLength());
        } else {
            xr = new XRoads(c, city.getXRoadsLength(), logger);
        }
        city.addXRoads(xr);
        return xr;
    }

    //letrehoz egy uj bankot
    public NotRoad createBank() {
        NotRoad bank = new NotRoad();
        bank.setPlace(Place.BANK);
        city.addBank(bank);
        logger.addMessage(bank.getName() + " created");
        return bank;
    }

    //letrehoz egy uj rejtekhelyet
    public NotRoad createHideout() {
        NotRoad hideout = new NotRoad();
        hideout.setPlace(Place.HIDEOUT);
        city.addHideout(hideout);
        logger.addMessage(hideout.getName() + " created");
        return hideout;
    }

    //letrehoz egy uj rendorseget
    public NotRoad createPoliceStation() {
        NotRoad policedept = new NotRoad();
        policedept.setPlace(Place.POLICEDEPT);
        city.addPoliceStation(policedept);
        logger.addMessage(policedept.getName() + " created");
        return policedept;
    }

    //meghivja sorban az osszes utemezheto objektum koret
    //a City-n keresztul
    public void tick() {
        turns++;
        //ha a körök száma osztható 6-tal
        if (running && turns%20==0)
        {
            processCommand("spawnPoliceAtStation");
        }
        if (running && turns%30==0)
        {
            processCommand("spawnBunny");
        }
        if (running) {
            city.tickCriminal();
        }
        if (running) {
            city.tickPolice();
        }
        if (running) {
            city.tickCitizens();
        }
        if (running) {
            city.TickLights();
        }
        processCommand("showMap");
    }

    //uj varost vesz fel, ezaltal a garbage collector
    //elobb-utobb eltunteti a regit, minden rajta levo objektummal egyutt
    public void eraseCity() {
        city = new City();
        ticker = new Ticker(this);
        running = true;
    }

    //visszater a menube - jelenleg nincs menu, a jatekot allitja meg
    public void returnToMenu() {
        running = false;
    }

    //a bankrablot elfogtak
    public void busted() {
        logger.addMessage("Criminal got busted");
        displayControl.displayBusted();
    }

    //a bankrablo civillel utkozott
    public void wasted() {
        logger.addMessage("Criminal got wasted");
        displayControl.displayWasted();
    }

    //a bankrablo megmenekult
    public void winGame() {
        logger.addMessage("Criminal won");
        displayControl.displayWin();
    }

    //elkezd egy uj jatekot
    public void gameStart() {
        processCommand("loadMap palya_1.txt");
        turns=0;
        ticker = new Ticker(this);
    }

    //igazat ad vissza, ha a jatek fut
    public boolean isRunning() {
        return running;
    }

    //bevolvasás után értékeli, és feldolgoza a parancsokat
    public void processCommand(String cmd) {
        StringTokenizer strTok = new StringTokenizer(cmd, " ");
        String command = strTok.nextToken();
        //kiírja milyen parancsok vannak (akár egy help)
        if ("listCommands".startsWith(command)) {
            System.out.println("listCommands - kiirja a standard kimenetre az elerheto parancsokat");
            System.out.println("loadCommands <filenev> - kulso fajlbol olvassa be a parancsokat");
            System.out.println("logToFile <filenev> - a log tartalmat kimenti kulso fajlba");
            System.out.println("loadMap <filenev> - kulso fajlbol kiolvassa a terkepet es felepiti\n"
                    + "az alapjan a varost");
            System.out.println("tick <korok szama> - megadott szamu kort szimulal.");
            System.out.println("turn [EAST|NORTH|WEST|SOUTH] - bankrablot elinditja adott iranyba");
            System.out.println("stopCriminal - megallitja a bankrablot");
            System.out.println("showMap - megmutatja az aktualis allapotot");
            System.out.println("spawnBunny - nyuszit letrehozza");
            System.out.println("forceBunnyTimeout - nyul hatasat semlegesiti");
            System.out.println("spawnPoliceAtStation - uj rendort hoz letre a rendorsegen");
            System.out.println("runTests - vegrehajtja mind a 8 tesztpalyat");
            System.out.println("exit - abbahagyja a tesztelest\n");
            return;
            // külső fájlban is lehet parancsokat megadni, és ezt a fájlt olvassa be
        } else if ("loadCommands".startsWith(command)) {
            String fileName = "";
            try {
                fileName = readToken(strTok);
                //a különböző platformok máshogy kezelik a könyvtárakat
                FileInputStream fis = new FileInputStream(System.getProperty("user.dir") + System.getProperty("file.separator") + fileName);
                InputStreamReader isr = new InputStreamReader(fis);
                BufferedReader br = new BufferedReader(isr);
                while (true) {
                    try {
                        String comm = br.readLine();
                        processCommand(comm);
                    } catch (IOException e) {
                        //vége a bemenetnek
                        return;
                    }
                }
            } //ha nem található a megadott file
            catch (FileNotFoundException e) {
                logger.addMessage("Error: FileNotFound");
                return;
            } //ha nem adtak meg file nevet
            catch (Exception e) {
                return;
            }

        } // kiírja a kimenetet egy fájlba
        else if ("logToFile".startsWith(command)) {

            String fileName;
            try {
                fileName = readToken(strTok);
                logger.printLogToFile(fileName);
            } catch (Exception e) {
                logger.addMessage(e.getMessage());
            }
        } //betölti a térképet adott fájlból
        else if ("loadMap".startsWith(command)) {
            String fileName;
            //térkép objektumokkal
            ArrayList<String> fullMap = new ArrayList<String>();
            //átmeneti tároló az össze mezőhöz
            ArrayList<Field> fields = new ArrayList<Field>();
            //térkép csak útelemekkel
            ArrayList<String> roadMap = new ArrayList<String>();
            try {
                fileName = readToken(strTok);
                FileInputStream fis = new FileInputStream(System.getProperty("user.dir") + System.getProperty("file.separator") + fileName);
                InputStreamReader isr = new InputStreamReader(fis);
                BufferedReader br = new BufferedReader(isr);
                //értéke addig true, amíg az utakat olvassuk be (térkép felső része))
                boolean readingRoads = true;
                //új városra van szükség
                eraseCity();
                //addig olvassuk a fájlt, amíg kivételt nem dob
                while (true) {
                    try {
                        String mapLine = br.readLine();
                        //ha csillaggal kezdődik egy sor
                        //elkezdheti az eddigi információkat feldolgozni
                        //és átválthat az objektumok olvasására
                        if (mapLine.startsWith("*")) {
                            readingRoads = false;
                            //minden eddigi sorra
                            for (String line : roadMap) {
                                for (int i = 0; i < line.length(); i++) {
                                    String sign = line.substring(i, i + 1);
                                    // üres mező felvétele
                                    if (sign.equals(" ")) {
                                        fields.add(null);
                                    } // út mező felvétele
                                    else if (sign.matches("[<>v^\\/]")) {
                                        Road r = createRoad();
                                        fields.add(r);
                                        r.setMark(sign);
                                        logger.addMessage(r.name + " created");
                                    } // bank felvétele
                                    else if (sign.equals("$")) {
                                        NotRoad bank = createBank();
                                        fields.add(bank);
                                        bank.setMark(sign);
                                    } // rendőrség felvétele
                                    else if (sign.equals("D")) {
                                        NotRoad policedept = createPoliceStation();
                                        fields.add(policedept);
                                        policedept.setMark(sign);
                                    } // rejtekhely felvétele
                                    else if (sign.equals("H")) {
                                        NotRoad hideout = createHideout();
                                        fields.add(hideout);
                                        hideout.setMark(sign);
                                    } // lámpa nélkül kereszteződés felvétele
                                    else if (sign.equals("+")) {
                                        XRoads xr = createXRoads(null);
                                        fields.add(xr);
                                        xr.setMark(sign);
                                        logger.addMessage(xr.name + " created");
                                    } // lámpás kereszteződés, dél felé zöld
                                    else if (sign.equals("S")) {
                                        XRoads xr = createXRoads(Compass.SOUTH);
                                        fields.add(xr);
                                        xr.setMark(sign);
                                        logger.addMessage(xr.getName() + " created");
                                        for (int k = 0; k < 4; k++) {
                                            logger.addMessage("TrafficLight[" + k + "] created on " + xr.getName());
                                        }
                                        logger.addMessage("TrafficLight[3] on XRoads[" + (city.getXRoadsLength() - 1) + "] turned green facing [SOUTH]");
                                    } // lámpás kereszteződés, kelet felé zöld
                                    else if (sign.equals("E")) {
                                        XRoads xr = createXRoads(Compass.EAST);
                                        fields.add(xr);
                                        xr.setMark(sign);
                                        logger.addMessage(xr.getName() + " created");
                                        for (int k = 0; k < 4; k++) {
                                            logger.addMessage("TrafficLight[" + k + "] created on " + xr.getName());
                                        }
                                        logger.addMessage("TrafficLight[0] on XRoads[" + (city.getXRoadsLength() - 1) + "] turned green facing [EAST]");
                                    } // lámpás kereszteződés, észak felé zöld
                                    else if (sign.equals("N")) {
                                        XRoads xr = createXRoads(Compass.NORTH);
                                        fields.add(xr);
                                        xr.setMark(sign);
                                        logger.addMessage(xr.getName() + " created");
                                        for (int k = 0; k < 4; k++) {
                                            logger.addMessage("TrafficLight[" + k + "] created on " + xr.getName());
                                        }
                                        logger.addMessage("TrafficLight[1] on XRoads[" + (city.getXRoadsLength() - 1) + "] turned green facing [NORTH]");
                                    } // lámpás kereszteződés, nyugat felé zöld
                                    else if (sign.equals("W")) {
                                        XRoads xr = createXRoads(Compass.WEST);
                                        fields.add(xr);
                                        xr.setMark(sign);
                                        logger.addMessage(xr.getName() + " created");
                                        for (int k = 0; k < 4; k++) {
                                            logger.addMessage("TrafficLight[" + k + "] created on " + xr.getName());
                                        }
                                        logger.addMessage("TrafficLight[2] on XRoads[" + (city.getXRoadsLength() - 1) + "] turned green facing [WEST]");
                                    }
                                }
                            }

                            // következik az utak összekapcsolása
                            for (int i = 0; i < roadMap.size(); i++) {
                                String line = roadMap.get(i);
                                for (int j = 0; j < line.length(); j++) {
                                    String sign = line.substring(j, j + 1);
                                    try {
                                        //üres út esetén nem kell kötni
                                        if (sign.equals(" ")) {
                                        } //ha az ut nem a térkép jobb széle és keletre mutat
                                        else if (j != line.length() - 1 && sign.equals(">")) {
                                            Road from = (Road) fields.get(i * line.length() + j);
                                            Field to = fields.get(i * line.length() + j + 1);
                                            city.linkFields(from, to, Compass.EAST);
                                        } //ha az ut nem a térkép bal széle és nyugatra mutat
                                        else if (j != 0 && sign.equals("<")) {
                                            Road from = (Road) fields.get(i * line.length() + j);
                                            Field to = fields.get(i * line.length() + j - 1);
                                            city.linkFields(from, to, Compass.WEST);
                                        } //ha az út nem az első sorban van és északra mutat
                                        else if (i != 0 && sign.equals("^")) {
                                            Road from = (Road) fields.get(i * line.length() + j);
                                            Field to = fields.get((i - 1) * line.length() + j);
                                            city.linkFields(from, to, Compass.NORTH);
                                        } //ha az út nem az utolsó sorban van és délre mutat
                                        else if (i != roadMap.size() - 1 && sign.equals("v")) {
                                            Road from = (Road) fields.get(i * line.length() + j);
                                            Field to = fields.get((i + 1) * line.length() + j);
                                            city.linkFields(from, to, Compass.SOUTH);
                                        } // ha D-K / NY-É kanyarodó út
                                        else if (sign.equals("/")) {
                                            Road from = (Road) fields.get(i * line.length() + j);
                                            //ha nyugatról vagy északról jön
                                            if (from.getNeighbour(0) != null) {
                                                //ha nyugatról jön, akkor északnak tart
                                                if (from.getNeighbour(0).getCompass() == Compass.WEST) {
                                                    Field to = fields.get((i - 1) * line.length() + j);
                                                    city.linkFields(from, to, Compass.NORTH);
                                                } //fordítva
                                                else {
                                                    Field to = fields.get(i * line.length() + j - 1);
                                                    city.linkFields(from, to, Compass.WEST);
                                                }
                                            } //ha délről, vagy keletről jön
                                            else {
                                                //ha a tőle jobbra lévő elem keleti irányba haladó út
                                                //délről keletre vezet
                                                if (line.substring(j + 1, j + 2).equals(">")) {
                                                    Field to = fields.get(i * line.length() + j + 1);
                                                    city.linkFields(from, to, Compass.EAST);
                                                } //fordítva
                                                else {
                                                    Field to = fields.get((i + 1) * line.length() + j);
                                                    city.linkFields(from, to, Compass.SOUTH);
                                                }
                                            }
                                        } // ha "negatív kanyarodó út"
                                        else if (sign.equals("\\")) {
                                            Road from = (Road) fields.get(i * line.length() + j);
                                            //ha nyugatról vagy északról jön
                                            if (from.getNeighbour(0) != null) {
                                                //ha nyugatról, délnek tart
                                                if (from.getNeighbour(0).getCompass() == Compass.WEST) {
                                                    Field to = fields.get((i + 1) * line.length() + j);
                                                    city.linkFields(from, to, Compass.SOUTH);
                                                } //ha északról, keletnek
                                                else {
                                                    Field to = fields.get(i * line.length() + j + 1);
                                                    city.linkFields(from, to, Compass.EAST);
                                                }
                                            } //ha délről vagy keletről jön
                                            else {
                                                //ha keletről, északnak tart
                                                if (line.substring(j, j + 1).equals("<")) {
                                                    Field to = fields.get((i - 1) * line.length() + j);
                                                    city.linkFields(from, to, Compass.NORTH);
                                                } //ha délről, nyugatnak
                                                else {
                                                    Field to = fields.get(i * line.length() + j - 1);
                                                    city.linkFields(from, to, Compass.WEST);
                                                }
                                            }
                                        } //speciális elemeknek pontosan egy Road szomszédjuk van,
                                        //tehát ki kell választani azt az utat ami a helyes irányba
                                        //vezet ki belőle
                                        else if (sign.matches("[$DH]")) {
                                            Field from = fields.get(i * line.length() + j);
                                            //ha a kaleti szomszéd keletre tart
                                            try {
                                                if (j != line.length() - 1 && line.substring(j + 1, j + 2).equals(">")) {
                                                    Field to = fields.get(i * line.length() + j + 1);
                                                    city.linkFields(from, to, Compass.EAST);
                                                }
                                            } catch (NullPointerException e) {
                                            }
                                            // ha a déli szomszéd délre tart
                                            try {
                                                if (i != roadMap.size() - 1 && roadMap.get(i + 1).substring(j, j + 1).equals("v")) {
                                                    Field to = fields.get((i + 1) * line.length() + j);
                                                    city.linkFields(from, to, Compass.SOUTH);
                                                }
                                            } catch (NullPointerException e) {
                                            }
                                            // ha a nyugati szomszéd nyugatnak tart
                                            try {
                                                if (j != 0 && line.substring(j - 1, j).equals("<")) {
                                                    Field to = fields.get(i * line.length() + j - 1);
                                                    city.linkFields(from, to, Compass.WEST);
                                                }
                                            } catch (NullPointerException e) {
                                            }
                                            // ha az északi szomszéd északnak tart
                                            try {
                                                if (i != 0 && roadMap.get(i - 1).substring(j, j + 1).equals("^")) {
                                                    Field to = fields.get((i - 1) * line.length() + j);
                                                    city.linkFields(from, to, Compass.NORTH);
                                                }
                                            } catch (NullPointerException e) {
                                            }
                                        }
                                    } catch (NullPointerException e) {
                                    }
                                }
                            }
                            //már csak a kereszteződésből induló utakra van szükség
                            for (int i = 0; i < roadMap.size(); i++) {

                                String line = roadMap.get(i);
                                for (int j = 0; j < line.length(); j++) {
                                    String sign = line.substring(j, j + 1);
                                    //kereszteződés esetén
                                    //végignézzük, hogy milyen iránybanincs még szomszéd és
                                    //felvesszük
                                    if (sign.matches("[+WSNE]")) {
                                        XRoads from = (XRoads) fields.get(i * line.length() + j);
                                        //ha keletre még nincs és az keletre tart
                                        if (!from.hasNeighbour(Compass.EAST)) {
                                            if (j != line.length() - 1 && line.substring(j + 1, j + 2).equals(">")) {
                                                Field to = fields.get(i * line.length() + j + 1);
                                                city.linkFields(from, to, Compass.EAST);
                                            }
                                        }
                                        //ha nyugatra még nincs és az nyugatra tart
                                        if (!from.hasNeighbour(Compass.WEST)) {
                                            if (j != 0 && line.substring(j - 1, j).equals("<")) {
                                                Field to = fields.get(i * line.length() + j - 1);
                                                city.linkFields(from, to, Compass.WEST);
                                            }
                                        }
                                        //ha északi még nincs és az északra tart
                                        if (!from.hasNeighbour(Compass.NORTH)) {
                                            if (i != 0 && roadMap.get(i - 1).substring(j, j + 1).equals("^")) {
                                                Field to = fields.get((i - 1) * line.length() + j);
                                                city.linkFields(from, to, Compass.NORTH);
                                            }
                                        }
                                        //ha déli még nincs és az délnek tart
                                        if (!from.hasNeighbour(Compass.SOUTH)) {
                                            if (i != roadMap.size() - 1 && roadMap.get(i + 1).substring(j, j + 1).equals("v")) {
                                                Field to = fields.get((i + 1) * line.length() + j);
                                                city.linkFields(from, to, Compass.SOUTH);
                                            }
                                        }
                                    }
                                }
                            }
                            city.linkFields(city.getRoad(city.getRoadLength()-1), city.getRoad(0), Compass.EAST);
                        } //ha nem feldolgoz, hanem olvas,
                        else {
                            //amíg a felső felét olvassa
                            if (readingRoads) {
                                if (mapLine.matches("^[ ><v+WESN/\\D$H^]*")) {
                                    roadMap.add(mapLine);
                                } else {
                                    logger.addMessage("Error: MapError");
                                    return;
                                }
                            } //amíg az alsó felét olvassa
                            else {
                                if (mapLine.matches("^[ ><v+WESN/\\D$HCYsPLTV^]*")) {
                                    fullMap.add(mapLine);
                                } else {
                                    //ha hiba történt a város építése után, rollback
                                    eraseCity();
                                    logger.addMessage("Error: MapError");
                                    return;
                                }
                            }
                        }
                    } 
                    //ha vége a bemeneti fájlnak
                    catch (IOException e) {}
                }
            }
            // ha a fájl nem található
            catch (FileNotFoundException e) {
                logger.addMessage("Error: FileNotFound");
                return;
            }
            catch (Exception e) {}

            //ha már mindent sikeresen beolvasott, megkezdődhet az utak feltöltése
            for (int i = 0; i < fullMap.size(); i++) {
                String line = fullMap.get(i);
                for (int j = 0; j < line.length(); j++) {
                    String sign = line.substring(j, j + 1);
                    //az adott útra felvesz egy bankrablót
                    if (sign.equals("C")) {
                        Field f = fields.get(i * line.length() + j);
                        Criminal cr = new Criminal(this);
                        city.addCriminal(cr);
                        f.setVehicle(cr);
                        cr.setField(f);
                        logger.addMessage("Criminal created and put on " + f.getName());
                    }
                    //az adott útra felvesz egy rendőrt
                    else if (sign.equals("P")) {
                        Field f = fields.get(i * line.length() + j);
                        Police p = new Police(this, city.getPoliceLength());
                        city.addPolice(p);
                        f.setVehicle(p);
                        p.setField(f);
                        logger.addMessage(p.getName() + " created and put on " + f.getName());
                    }
                    //az adott útra felvesz egy gyors autót
                    else if (sign.equals("L")) {
                        Field f = fields.get(i * line.length() + j);
                        Citizen c = new Citizen(this, city.getCitizenLength());
                        city.addCitizen(c);
                        c.setType(CitizenType.LAMBORGHINI);
                        f.setVehicle(c);
                        c.setField(f);
                        logger.addMessage(c.getName() + " created and put on " + f.getName());
                    }
                    //az adott útra felvesz egy lassú autót
                    else if (sign.equals("T")) {
                        Field f = fields.get(i * line.length() + j);
                        Citizen c = new Citizen(this, city.getCitizenLength());
                        city.addCitizen(c);
                        c.setType(CitizenType.TRABANT);
                        f.setVehicle(c);
                        c.setField(f);
                        logger.addMessage(c.getName() + " created and put on " + f.getName());
                    }
                    //az adott útra felvesz egy közepes autót
                    else if (sign.equals("V")) {
                        Field f = fields.get(i * line.length() + j);
                        Citizen c = new Citizen(this, city.getCitizenLength());
                        city.addCitizen(c);
                        c.setType(CitizenType.VOLKSWAGEN);
                        f.setVehicle(c);
                        c.setField(f);
                        logger.addMessage(c.getName() + " created and put on " + f.getName());
                    }
                    //adott útra helyez egy húsvéti nyuszit
                    else if (sign.equals("Y")) {
                        Field f = fields.get(i * line.length() + j);
                        f.setPower(PowerUp.EASTERBUNNY);
                        logger.addMessage("Easter Bunny put on " + f.getName());
                    }
                    //adott útra helyez egy stoptáblát
                    else if (sign.equals("s")) {
                        Road r = (Road) fields.get(i * line.length() + j);
                        r.setSign(true);
                        logger.addMessage("Stopsign put on " + r.getName());
                    }
                }
            }
            //elmenti a térkép vázát
            logger.setRoadMap(roadMap);
            //elmenti a térképet
            logger.setMap(fullMap);
            displayControl.initMap(roadMap);
            displayControl.forceDisplay(fullMap);
            return;
        }
        // adott számnyit tickkel
        else if ("tick".startsWith(command)) {
            //megpróbálja a megadott paramétert számmá konvertálni,
            //majd annyit tickel, amennyi adódott
            try {
                int turns = Integer.parseInt(readToken(strTok));
                for (int i = 1; i <= turns; i++) {
                    tick();
                }
                return;
            }
            // ha nem megfelelő paramétert adtunk meg
            catch (NumberFormatException e) {
                logger.addMessage("Error: ParameterError");
                return;
            }
            // ha nem egyezik a paraméterszám
            catch (Exception e) {
                logger.addMessage(e.getMessage());
                return;
            }

        // bankrabló fordulási irányát lehet megadni
        } else if ("turn".startsWith(command)) {

            try {
                Criminal cr = city.getCriminal();
                String compass = readToken(strTok);
                if (compass.equals("EAST")) {
                    cr.setCompass(Compass.EAST);
                } else if (compass.equals("WEST")) {
                    cr.setCompass(Compass.WEST);
                } else if (compass.equals("NORTH")) {
                    cr.setCompass(Compass.NORTH);
                } else if (compass.equals("SOUTH")) {
                    cr.setCompass(Compass.SOUTH);
                }
                // a paraméter nem megfelelő
                else {
                    logger.addMessage("Error: ParameterError");
                }
                return;
            }
            //ha a bankrabló referenciája nem elérhető
            catch (NullPointerException e) {
                logger.addMessage("Error: CriminalNotFound");
                return;
            }
            // ha a paraméterek száma nem stimmel
            catch (Exception e) {
                logger.addMessage(e.getMessage());
                return;
            }
        }
        // megállítja a bankrablót
        else if ("stopCriminal".startsWith(command)) {
            Criminal cr;
            try {
                cr = city.getCriminal();
                cr.forceStop();
                return;
            }
            //nem található a bankrabló
            catch (NullPointerException e) {
                logger.addMessage("Error: CriminalNotFound");
                return;
            }
        }
        //kirajzolja a térképet
        else if ("showMap".startsWith(command)) {
            int xroadsCount = 0;
            int roadCount = 0;
            // térkép szerkezet
            ArrayList<String> map = logger.getMap();
            //aktuális állapot
            ArrayList<String> newmap = new ArrayList<String>();
            if (map.size() == 0) {
                logger.addMessage("Error: MapNotFound");
                return;
            }
            //a szerkezet karakterein véghaladva
            //lekérdezi az aktuláis állapotot
            //az adott utakra vonatkozóan
            //és az új térképre feltölti azt
            for (int i = 0; i < map.size(); i++) {
                String mapLine = map.get(i);
                String newLine = new String("");
                for (int j = 0; j < mapLine.length(); j++) {
                    String oldSign = mapLine.substring(j, j + 1);
                    //kereszteződés esetén
                    if (oldSign.matches("[ESWN+]")) {
                        XRoads xr = city.getXRoads(xroadsCount);
                        oldSign = xr.getMark();
                        newLine = newLine.concat(oldSign);
                        xroadsCount++;
                    }
                    //út esetén
                    else if (oldSign.matches("[><v/\\^]")) {
                        Road r = city.getRoad(roadCount);
                        oldSign = r.getMark();
                        newLine = newLine.concat(oldSign);
                        roadCount++;
                    }
                    //banknál
                    else if (oldSign.equals("$")) {
                        oldSign = city.getBank().getMark();
                        newLine = newLine.concat(oldSign);
                    }
                    //rendőrségnél
                    else if (oldSign.equals("D")) {
                        oldSign = city.getPoliceStation().getMark();
                        newLine = newLine.concat(oldSign);
                    }
                    //rejtekhelynél
                    else if (oldSign.equals("H")) {
                        oldSign = city.getHideout().getMark();
                        newLine = newLine.concat(oldSign);
                    }
                    //üres mezőnél
                    else {
                        newLine = newLine.concat(oldSign);
                    }
                }
                newmap.add(newLine);
            }
            logger.setMap(newmap);
            logger.printMap();
            displayControl.forceDisplay(newmap);
            return;

            // elhelyezi a nyulat a bankrabló előtti mezőre
        } else if ("spawnBunny".startsWith(command)) {
            int r = city.getRoadLength();
            Road road = city.getRoad(turns%r);
            road.setPower(PowerUp.EASTERBUNNY);
        } 
        //megszünteti az elütött nyűl álltali védetséget
        else if ("forceBunnyTimeout".startsWith(command)) {
            try {
                Criminal cr = city.getCriminal();
                cr.setPower(PowerUp.NOPOWER);
                logger.addMessage("Easter Bunny evaluated");
                return;
            } catch (NullPointerException e) {
                logger.addMessage("Error: CriminalNotFound");
                return;
            }
        }
        // elhelyez egy rendőrt a rendőrségen
        else if ("spawnPoliceAtStation".startsWith(command)) {
            Field policest;
            try {
                policest = city.getPoliceStation();
            }
            //ha nem található a rendőrség
            catch (NullPointerException e) {
                logger.addMessage("Error: PoliceStationNotFound");
                return;
            }
            //ha nem foglalt, rárakja az új rendőrt
            if (!policest.checkOccupy()) {
                Police p1 = new Police(this, city.getPoliceLength());
                policest.setVehicle(p1);
                p1.setField(policest);
                city.addPolice(p1);
                logger.addMessage(p1.getName() + " created and put on " + policest.getName());
            } else {
                logger.addMessage("Error: PoliceStationOccupied");
            }
            return;
        }
        //végrehajta mind a 8 tesztesetet
        else if ("runTests".startsWith(command))
        {
            processCommand("loadCommands level1.txt");
            processCommand("loadCommands level2.txt");
            processCommand("loadCommands level3.txt");
            processCommand("loadCommands level4.txt");
            processCommand("loadCommands level5.txt");
            processCommand("loadCommands level6.txt");
            processCommand("loadCommands level7.txt");
            processCommand("loadCommands level8.txt");
        }
        // kilépés
        else if ("exit".startsWith(command)) {
            System.exit(0);
        }
        else if (command.startsWith("gameStart"))
        {
            ticker.tick();
        }
        // nem ismert parancsot adtak meg
        else {
            logger.addMessage("Error: CommandNotFound");
            return;
        }
    }

    // a következő stringet olvassa
    public String readToken(StringTokenizer st) throws Exception {
        if (st.hasMoreElements()) {
            return st.nextToken();
        } else {
            throw new Exception("Error: ParameterCountMismatch");
        }
    }
}
